﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Mrsoft.Common;

namespace Mrsoft.Core {
    public class DmLibary : IDisposable {
        #region 初始化按键码
        /// <summary>
        /// 静态构造函数
        /// 初始化按键码
        /// </summary>
        static DmLibary() {
            KeyDic = new Dictionary<string, int>();
            string[] keyvalueArr = (Properties.Resources.key).Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string str in keyvalueArr) {
                string[] temArr = str.Split(new[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                if (temArr.Length == 2) {
                    int temValue;
                    if (int.TryParse(temArr[1], out temValue)) {
                        KeyDic.Add(temArr[0].ToLower(), temValue);
                    }
                }
            }
        }

        public static Dictionary<string, int> KeyDic = null;
        #endregion

        #region 绑定模式
        const string display = "dx.graphic.3d";
        const string mouse = "dx.mouse.state.api|dx.mouse.focus.input.api|dx.mouse.api|dx.public.active.message|dx.public.active.api";
        const string keypad = "windows";
        const string publicMethod = "";
        #endregion

        #region 资源初始化与释放
        /// <summary>
        /// 大漠COM对象
        /// </summary>
        public Dm.Idmsoft _dm = null;
        /// <summary>
        /// DMLibary创建的次数统计
        /// </summary>
        private static int _iCreateCounter;

        private readonly int _hwnd;

        public DmLibary(int hwnd = -1, bool showError = true, bool loginDm = false) {
            try {
                _dm = new Dm.dmsoft();
            }
            catch {
                try {
                    //注册DM插件
                    NativeMethods.ComRegister(Directory.GetCurrentDirectory() + @"\插件\dm.dll");
                    _dm = new Dm.dmsoft();
                }
                catch {
                    _dm = new CDmSoft();
                    if (Interlocked.Increment(ref _iCreateCounter) == 1) {
                        MsgListener.CommonMsgShow("DM插件2", this._dm.Ver());
                    }
                }
            }
            if (Interlocked.Increment(ref _iCreateCounter) == 1) {
                MsgListener.CommonMsgShow("DM插件1", this._dm.Ver());
            }
            try {
                _dm.SetShowErrorMsg(0);
                if (_dm.SetDictPwd("sunyu87") == 0 || _dm.SetDict(0, @".\system\MyDict.txt") == 0)
                    throw new Exception("插件关键文件无法加载");
                if (hwnd > 0) {
                    if (!loginDm) {

                        if (_dm.BindWindowEx(hwnd, display, mouse, keypad, publicMethod, 0) == 0 &&
                            _dm.BindWindowEx(hwnd, display, mouse, keypad, publicMethod, 4) == 0)
                            throw new Exception("插件绑定游戏窗口失败" + _dm.GetLastError());
                    }
                    else {
                        var dx = "dx";
                        if (_dm.BindWindowEx(hwnd, display, mouse, dx, publicMethod, 0) == 0 &&
                            _dm.BindWindowEx(hwnd, display, mouse, dx, publicMethod, 4) == 0)
                            throw new Exception("插件绑定游戏窗口失败" + _dm.GetLastError());
                    }
                    _dm.SetMouseDelay("dx", 60);
                    _hwnd = hwnd;
                }
            }
            catch (Exception ex) {
                if (showError)
                    MsgListener.MsgBoxMsgShow(ex.Message, "DM插件错误");
                else
                    MsgListener.CommonMsgShow("插件DM", ex.Message);
                _dm = null;
                _hwnd = -1;
            }
        }

        public void Dispose() {
            if (_dm == null)
                return;
            _dm.UnBindWindow();
        }
        #endregion

        #region 常用方法体
        public bool GetClientSize(out int x, out int y) {
            x = y = -1;
            if (_dm == null)
                return false;
            object obj1, obj2;
            if (_dm.GetClientSize(_hwnd, out obj1, out obj2) == 1) {
                x = (int)obj1;
                y = (int)obj2;
                return true;
            }
            return false;
        }
        public void DownCpu(int downPercent) {
            if (_dm != null)
                _dm.DownCpu(downPercent);
        }
        public bool DmRcWord(string str, string color, out int wx, out int wy, int x1 = 0, int y1 = 0, int x2 = 2000, int y2 = 2000) {
            wx = (wy = -1);
            try {
                if (_dm == null)
                    return false;
                object obj;
                object obj2;
                if (this._dm.GetClientSize(_hwnd, out obj, out obj2) == 1) {
                    if (x2 > (int)obj) {
                        x2 = (int)obj;
                    }
                    if (y2 > (int)obj2) {
                        y2 = (int)obj2;
                    }
                }
                if (this._dm.FindStrFast(x1, y1, x2, y2, str, color, 1.0, out obj, out obj2) > -1) {
                    wx = (int)obj;
                    wy = (int)obj2;
                    return true;
                }
            }
            // ReSharper disable EmptyGeneralCatchClause
            catch
                // ReSharper restore EmptyGeneralCatchClause
            {
                //避免出现读取的时候的内存错误
            }
            return false;
        }
        public void DmClick(int x, int y, int times = 1, bool left = true) {
            if (_dm == null)
                return;
            bool flag = false;
            try {
                Monitor.Enter(this, ref flag);
                if (x > 0 && y > 0) {
                    this._dm.MoveTo(x, y);
                }
                var random = new Random();
                for (int i = 0; i < times; i++) {
                    if (left) {
                        this._dm.LeftClick();
                        this._dm.LeftUp();
                    }
                    else {
                        this._dm.RightClick();
                        this._dm.RightUp();
                    }
                    Thread.Sleep(random.Next(20, 30));
                }
            }
            finally {
                if (flag) {
                    Monitor.Exit(this);
                }
            }
        }
        public void DmKeyPress(string key, int times = 1) {
            if (_dm == null || !KeyDic.Keys.Contains(key.ToLower())) {
                return;
            }
            int keyNum = KeyDic[key.ToLower()];
            lock (this._dm) {
                for (int i = 0; i < times; i++) {
                    this._dm.KeyPress(keyNum);
                }
            }
        }
        public bool CapturePng(int x1, int y1, int x2, int y2, string file) {
            if (_dm == null)
                return false;
            return this._dm.CapturePng(x1, y1, x2, y2, file) == 1;
        }
        public bool CaptureJpg(int x1, int y1, int x2, int y2, string file, int quality = 100) {
            if (_dm == null)
                return false;
            return this._dm.CaptureJpg(x1, y1, x2, y2, file, quality) == 1;
        }
        public bool CaptureGif(int x1, int y1, int x2, int y2, string file, int delay = 0, int time = 0) {
            if (_dm == null)
                return false;
            return this._dm.CaptureGif(x1, y1, x2, y2, file, 0, 0) == 1;
        }
        public bool Capture(int x1, int y1, int x2, int y2, string fileName) {
            if (_dm == null)
                return false;
            return this._dm.Capture(x1, y1, x2, y2, fileName) == 1;
        }
        public int Play(string file) {
            if (_dm == null)
                return -1;
            return this._dm.Play(file);
        }
        public int SendString(int hwnd, string str) {
            if (_dm == null)
                return -1;
            return this._dm.SendString(hwnd, str);
        }
        public string Ocr(int x1, int y1, int x2, int y2, string color, double sim) {
            if (_dm == null)
                return "";
            return this._dm.Ocr(x1, y1, x2, y2, color, sim);
        }
        public void KeyUpChar(string str) {
            if (_dm == null || !KeyDic.Keys.Contains(str.ToLower())) {
                return;
            }
            this._dm.KeyUp(KeyDic[str.ToLower()]);
        }
        public void KeyPressChar(string str) {
            if (_dm == null || !KeyDic.Keys.Contains(str.ToLower())) {
                return;
            }
            this._dm.KeyPress(KeyDic[str.ToLower()]);
        }
        public string GetPath() {
            if (_dm == null)
                return "";
            return this._dm.GetPath();
        }
        public int SetWindowState(int flag) {
            if (_dm == null || _hwnd < 0) {
                return 0;
            }
            return this._dm.SetWindowState(_hwnd, flag);
        }
        public int FaqCapture(int x1, int y1, int x2, int y2, int quality, int delay, int time) {
            if (_dm == null)
                return 0;
            return this._dm.FaqCapture(x1, y1, x2, y2, quality, delay, time);
        }
        public void Stop(int id) {
            if (_dm == null)
                return;
            this._dm.Stop(id);
        }
        public int GetWindowState(int flag) {
            if (_dm == null)
                return 0;
            return this._dm.GetWindowState(_hwnd, flag);
        }
        #endregion
    }
}